/*
 * 说明：在rt_thread软件包的基础上，作了修改，在初始化文件max6675_init中增加了spi配置文件
 *  struct rt_spi_configuration cfg;
 *      cfg.data_width = 16;
 *      cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_2 | RT_SPI_MSB;
 *      cfg.max_hz = 20 * 1000 *1000;                           // 20M
 *
 *      按照max6675的传输方式，更改传输参数
 *     rt_spi_configure(dev->spi, &cfg); //配置传输模式
 *
 */


/*
 *注：按照默认值是读不出来数据的
 */

#include "max6675.h"
#include <rtthread.h>
#include "board.h"
#include <rtdbg.h>
#include <rtdevice.h>

#include "drv_soft_spi.h"
#include "sensor_maxim_max6675.h"

#define MAX667_SPI_BUS  "spi10"

/* 设置数据传输顺序是MSB位在前还是LSB位在前 */
#define RT_SPI_LSB      (0<<2)                        /* bit[2]: 0-LSB */
#define RT_SPI_MSB      (1<<2)                        /* bit[2]: 1-MSB */

/* 设置SPI的主从模式 */
#define RT_SPI_MASTER   (0<<3)                        /* SPI master device */
#define RT_SPI_SLAVE    (1<<3)                        /* SPI slave device */

/* 设置时钟极性和时钟相位 */
#define RT_SPI_MODE_0   (0 | 0)                       /* CPOL = 0, CPHA = 0 */
#define RT_SPI_MODE_1   (0 | RT_SPI_CPHA)             /* CPOL = 0, CPHA = 1 */
#define RT_SPI_MODE_2   (RT_SPI_CPOL | 0)             /* CPOL = 1, CPHA = 0 */
#define RT_SPI_MODE_3   (RT_SPI_CPOL | RT_SPI_CPHA)   /* CPOL = 1, CPHA = 1 */

#define RT_SPI_CS_HIGH  (1<<4)                        /* Chipselect active high */
#define RT_SPI_NO_CS    (1<<5)                        /* No chipselect */
#define RT_SPI_3WIRE    (1<<6)                        /* SI/SO pin shared */
#define RT_SPI_READY    (1<<7)                        /* Slave pulls low to pause */

rt_int32_t temp1 = 0;

int rt_hw_max6675_port(void)
{
    struct rt_sensor_config cfg;

    cfg.intf.dev_name  = MAX667_SPI_BUS;

    rt_hw_max6675_init("max6675", &cfg);

    return RT_EOK;
}
INIT_ENV_EXPORT(rt_hw_max6675_port);

static rt_err_t read_data(struct rt_spi_device *dev, rt_uint8_t *buf)
{
    rt_spi_recv(dev, buf, 2);
    //soft_spi_read_bytes(dev, buf, 2);
    return RT_EOK;
}

float max6675_read_temp(max6675_device_t dev)
{
    rt_uint8_t temp[2];
    float temperature = 0.0;
    rt_err_t result;

    result = rt_mutex_take(dev->lock, RT_WAITING_FOREVER);
    if(result == RT_EOK)
    {
        read_data(dev->spi, temp);
        if(!((temp[0] & 0x80) || (temp[1] &0x02)))
        {
            if(!(temp[1] & 0x04))
            {
                temperature = ((temp[0] << 8 | temp[1]) >> 3) / 4.0;
            }
        }
    }else
    {
        LOG_E("Failed to reading tempurature");
    }
    rt_mutex_release(dev->lock);

    return temperature;
}

/**
 * This function initializes max6675 registered device driver
 *
 * @param dev the name of max6675 device
 *
 * @return the max6675 device.
 */
max6675_device_t max6675_init(const char *spi_device_name)
{
    max6675_device_t dev;
    struct rt_spi_configuration cfg;
        cfg.data_width = 16;
        cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_2 | RT_SPI_MSB;
        cfg.max_hz = 20 * 1000 *1000;                           /* 20M */


    RT_ASSERT(spi_device_name);

    dev = rt_calloc(1, sizeof(struct max6675_device));
    if (dev == RT_NULL)
    {
        LOG_E("Can't allocate memory for max6675 device on '%s' ", spi_device_name);
        rt_free(dev);

        return RT_NULL;
    }

    rt_soft_spi_device_attach("spi0","spi10",RT_NULL,19);
    dev->spi =  (struct rt_spi_device *)(rt_device_find(spi_device_name));


    if (dev->spi == RT_NULL)
    {
        LOG_E("Can't find max6675 device on '%s'", spi_device_name);
        rt_free(dev);
        return RT_NULL;
    }

    rt_spi_configure(dev->spi, &cfg); //配置传输模式

    dev->lock = rt_mutex_create("mutex_max6675", RT_IPC_FLAG_FIFO);
    if (dev->lock == RT_NULL)
    {
        LOG_E("Can't create mutex for max6675 device on '%s'", spi_device_name);
        rt_free(dev);
        return RT_NULL;
    }

    return dev;
}

/**
 * This function releases memory and deletes mutex lock
 *
 * @param dev the pointer of device driver structure
 */
void max6675_deinit(max6675_device_t dev)
{
    RT_ASSERT(dev);

    rt_mutex_delete(dev->lock);

    rt_free(dev);
}


void max6675(int argc, char *argv[])
{
    static max6675_device_t dev = RT_NULL;


    if (argc > 1)
    {
        if (!strcmp(argv[1], "probe"))
        {
            if (argc > 2)
            {
                /* initialize the sensor when first probe */
                if (!dev || strcmp(dev->spi->parent.parent.name, argv[2]))
                {
                    /* deinit the old device */
                    if (dev)
                    {
                        max6675_deinit(dev);
                    }
                    dev = max6675_init(argv[2]);
                    //rt_spi_configure(dev, &cfg); //配置传输模式
                    //rt_kprintf("dev->config-mode",dev->spi->config->mode);
                }
            }
            else
            {
                rt_kprintf("max6675 probe <dev_name>   - probe sensor by given name\n");
            }
        }
        else if (!strcmp(argv[1], "read"))
        {
            if (dev)
            {
                float temp_data;

                /* read the sensor */
                temp_data = max6675_read_temp(dev);
                if (temp_data == 0)
                {
                    rt_kprintf("object is not proximity of sensor \n");
                }
                else
                {
                    rt_kprintf("max6675 read : %d.%d\n", (uint16_t)temp_data, ((uint16_t)(temp_data * 100)) % 100);
                }

            }
            else
            {
                rt_kprintf("Please using 'max6675 probe <dev_name>' first\n");
            }
        }
        else
        {
            rt_kprintf("Unknown command. Please enter 'max6675' for help\n");
        }
    }
    else
    {
        rt_kprintf("Usage:\n");
        rt_kprintf("max6675 probe <dev_name>   - probe sensor by given name\n");
        rt_kprintf("max6675 read               - read sensor max6675 data\n");
    }
}
MSH_CMD_EXPORT(max6675, max6675 sensor function);
